class_docstr: Creates a Generalized Universal Function by wrapping a user
  provided function with the signature.
  
  ``signature`` determines if the function consumes or produces core
  dimensions. The remaining dimensions in given input arrays (``*args``)
  are considered loop dimensions and are required to broadcast
  naturally against each other.
  
  Args:
      func (callable):
          Function to call like ``func(*args, **kwargs)`` on input arrays
          (``*args``) that returns an array or tuple of arrays. If
          multiple arguments with non-matching dimensions are supplied,
          this function is expected to vectorize (broadcast) over axes of
          positional arguments in the style of NumPy universal functions.
      signature (string):
          Specifies what core dimensions are consumed and produced by
          ``func``.  According to the specification of numpy.gufunc
          signature.
      supports_batched (bool, optional):
          If the wrapped function supports to pass the complete input
          array with the loop and the core dimensions.
          Defaults to `False`. Dimensions will be iterated in the
          `GUFunc` processing code.
      supports_out (bool, optional):
          If the wrapped function supports out as one of its kwargs.
          Defaults to `False`.
      signatures (list of tuple of str):
          Contains strings in the form of 'ii->i' with i being the char of a
          dtype. Each element of the list is a tuple with the string
          and a alternative function to `func` to be executed when the inputs
          of the function can be casted as described by this function.
      name (str, optional):
          Name for the GUFunc object. If not specified, ``func``'s name
          is used.
      doc (str, optional):
          Docstring for the GUFunc object. If not specified, ``func.__doc__``
          is used.
code: def _apply_func_to_inputs(self, func, dim, sizes, dims, args, outs):
      # Apply function
      # The resulting array is loop_output_dims+the specified dims
      # Some functions have batching logic inside due to higly
      # optimized CUDA libraries so we just call them
      if self._supports_batched or dim == len(dims):
          # Check if the function supports out, order and other args
          if self._supports_out and outs is not None:
              outs = outs[0] if len(outs) == 1 else outs
              func(*args, out=outs)
          else:
              fouts = func(*args)
              # TODO(ecastill) improve this check
              if isinstance(fouts, cupy.ndarray):
                  fouts = (fouts,)
              for o, fo in zip(outs, fouts):
                  cupy._core.elementwise_copy(fo, o)
      else:
          dim_size = sizes[dims[dim]][0]
          for i in range(dim_size):
              n_args = [a[i] for a in args]
              if outs is not None:
                  n_outs = [o[i] for o in outs]
                  self._apply_func_to_inputs(
                      func, dim + 1, sizes, dims, n_args, n_outs
                  )
  
imports: import re
  import numpy
  import cupy
  import cupy._core._routines_manipulation
  from cupy._core._dtype import get_dtype, _raise_if_invalid_cast
  from cupy._core import internal
label_desc: Use image node_id 2 for calling the _GUFunc obj's underlying member method code with example usage: obj._apply_func_to_inputs(func, dim, sizes, dims, args, outs) without return types