Draw random samples from a normal (Gaussian) distribution.

    Samples are distributed according to a normal distribution parametrized
    by *loc* (mean) and *scale* (standard deviation).


    Parameters
    ----------
    loc : float or NDArray
        Mean (centre) of the distribution.
    scale : float or NDArray
        Standard deviation (spread or width) of the distribution.
    shape : int or tuple of ints
        The number of samples to draw. If shape is, e.g., `(m, n)` and `loc` and
        `scale` are scalars, output shape will be `(m, n)`. If `loc` and `scale`
        are NDArrays with shape, e.g., `(x, y)`, then output will have shape
        `(x, y, m, n)`, where `m*n` samples are drawn for each `[loc, scale)` pair.
    dtype : {'float16', 'float32', 'float64'}
        Data type of output samples. Default is 'float32'
    ctx : Context
        Device context of output. Default is current context. Overridden by
        `loc.context` when `loc` is an NDArray.
    out : NDArray
        Store output to an existing NDArray.

    Returns
    -------
    NDArray
        If input `shape` has shape, e.g., `(m, n)` and `loc` and `scale` are scalars, output
        shape will be `(m, n)`. If `loc` and `scale` are NDArrays with shape, e.g., `(x, y)`,
        then output will have shape `(x, y, m, n)`, where `m*n` samples are drawn for
        each `[loc, scale)` pair.

    Examples
    --------
    >>> mx.nd.random.randn()
    2.21220636
    <NDArray 1 @cpu(0)>
    >>> mx.nd.random.randn(2, 2)
    [[-1.856082   -1.9768796 ]
    [-0.20801921  0.2444218 ]]
    <NDArray 2x2 @cpu(0)>
    >>> mx.nd.random.randn(2, 3, loc=5, scale=1)
    [[4.19962   4.8311777 5.936328 ]
    [5.357444  5.7793283 3.9896927]]
    <NDArray 2x3 @cpu(0)>

def randn(*shape, **kwargs):
    """Draw random samples from a normal (Gaussian) distribution.

    Samples are distributed according to a normal distribution parametrized
    by *loc* (mean) and *scale* (standard deviation).


    Parameters
    ----------
    loc : float or NDArray
        Mean (centre) of the distribution.
    scale : float or NDArray
        Standard deviation (spread or width) of the distribution.
    shape : int or tuple of ints
        The number of samples to draw. If shape is, e.g., `(m, n)` and `loc` and
        `scale` are scalars, output shape will be `(m, n)`. If `loc` and `scale`
        are NDArrays with shape, e.g., `(x, y)`, then output will have shape
        `(x, y, m, n)`, where `m*n` samples are drawn for each `[loc, scale)` pair.
    dtype : {'float16', 'float32', 'float64'}
        Data type of output samples. Default is 'float32'
    ctx : Context
        Device context of output. Default is current context. Overridden by
        `loc.context` when `loc` is an NDArray.
    out : NDArray
        Store output to an existing NDArray.

    Returns
    -------
    NDArray
        If input `shape` has shape, e.g., `(m, n)` and `loc` and `scale` are scalars, output
        shape will be `(m, n)`. If `loc` and `scale` are NDArrays with shape, e.g., `(x, y)`,
        then output will have shape `(x, y, m, n)`, where `m*n` samples are drawn for
        each `[loc, scale)` pair.

    Examples
    --------
    >>> mx.nd.random.randn()
    2.21220636
    <NDArray 1 @cpu(0)>
    >>> mx.nd.random.randn(2, 2)
    [[-1.856082   -1.9768796 ]
    [-0.20801921  0.2444218 ]]
    <NDArray 2x2 @cpu(0)>
    >>> mx.nd.random.randn(2, 3, loc=5, scale=1)
    [[4.19962   4.8311777 5.936328 ]
    [5.357444  5.7793283 3.9896927]]
    <NDArray 2x3 @cpu(0)>
    """
    loc = kwargs.pop('loc', 0)
    scale = kwargs.pop('scale', 1)
    dtype = kwargs.pop('dtype', _Null)
    ctx = kwargs.pop('ctx', None)
    out = kwargs.pop('out', None)
    assert isinstance(loc, (int, float))
    assert isinstance(scale, (int, float))
    return _random_helper(_internal._random_normal, _internal._sample_normal,
                          [loc, scale], shape, dtype, ctx, out, kwargs)