(fun)
return batch_wrapper
Decorator which applies a function along the first dimension of a given data matrix (the batch dimension).
    
    The most common use case is to convert a function designed to operate on a single input vector, and
    to compute its response (and possibly gradient) for each row of a matrix.

    :param fun: function accepting an input vector of size D and returns a vector of size R (number of 
        outputs) and (optionally) a gradient of size D x R (or size D if R == 1)
    :return: a function wrapper which calls fun on each row of a given N* x D matrix. Here N* represents the batch
        dimension. The wrapper returns N* x R and optionally a matrix, size N* x D x R matrix (or size N* x D if R == 1)
Decorator which applies a function along the first dimension of a given data matrix (the batch dimension).
    
    The most common use case is to convert a function designed to operate on a single input vector, and
    to compute its response (and possibly gradient) for each row of a matrix.
Decorator which applies a function along the first dimension of a given data matrix ( the batch dimension ) . The most common use case is to convert a function designed to operate on a single input vector and to compute its response ( and possibly gradient ) for each row of a matrix .
def batch_apply(fun):
    """
    Decorator which applies a function along the first dimension of a given data matrix (the batch dimension).
    
    The most common use case is to convert a function designed to operate on a single input vector, and
    to compute its response (and possibly gradient) for each row of a matrix.

    :param fun: function accepting an input vector of size D and returns a vector of size R (number of 
        outputs) and (optionally) a gradient of size D x R (or size D if R == 1)
    :return: a function wrapper which calls fun on each row of a given N* x D matrix. Here N* represents the batch
        dimension. The wrapper returns N* x R and optionally a matrix, size N* x D x R matrix (or size N* x D if R == 1)
    """
    @wraps(fun)
    def batch_wrapper(X):
        responses = (fun(x) for x in np.atleast_2d(X))
        sep = tuple(zip(*(r if isinstance(r, tuple) else (r,) for r in responses)))
        f = np.vstack(sep[0])
        if len(sep) == 1:
            return f

        # for each point, the gradient is either (D,) or (D, R) shaped.
        g_stacked = np.stack((r for r in sep[1]), axis=0)  # N x D or N x D x R
        # Get rid of last dim = 1 in case R = 1
        g = np.squeeze(g_stacked, axis=2) if len(g_stacked.shape) == 3 and g_stacked.shape[2] == 1 else g_stacked
        return f, g

    return batch_wrapper
def batch_apply ( fun ) : @ wraps ( fun ) def batch_wrapper ( X ) : responses = ( fun ( x ) for x in np . atleast_2d ( X ) ) sep = tuple ( zip ( * ( r if isinstance ( r , tuple ) else ( r , ) for r in responses ) ) ) f = np . vstack ( sep [ 0 ] ) if len ( sep ) == 1 : return f # for each point, the gradient is either (D,) or (D, R) shaped. g_stacked = np . stack ( ( r for r in sep [ 1 ] ) , axis = 0 ) # N x D or N x D x R # Get rid of last dim = 1 in case R = 1 g = np . squeeze ( g_stacked , axis = 2 ) if len ( g_stacked . shape ) == 3 and g_stacked . shape [ 2 ] == 1 else g_stacked return f , g return batch_wrapper