Apply a variable level function over DataArray, Variable and/or ndarray
    objects.

def apply_dataarray_vfunc(
    func,
    *args,
    signature,
    join='inner',
    exclude_dims=frozenset(),
    keep_attrs=False
):
    """Apply a variable level function over DataArray, Variable and/or ndarray
    objects.
    """
    from .dataarray import DataArray

    if len(args) > 1:
        args = deep_align(args, join=join, copy=False, exclude=exclude_dims,
                          raise_on_invalid=False)

    if keep_attrs and hasattr(args[0], 'name'):
        name = args[0].name
    else:
        name = result_name(args)
    result_coords = build_output_coords(args, signature, exclude_dims)

    data_vars = [getattr(a, 'variable', a) for a in args]
    result_var = func(*data_vars)

    if signature.num_outputs > 1:
        out = tuple(DataArray(variable, coords, name=name, fastpath=True)
                    for variable, coords in zip(result_var, result_coords))
    else:
        coords, = result_coords
        out = DataArray(result_var, coords, name=name, fastpath=True)

    return out