code: def gradients(
      func_or_y,
      xs,
      output_gradients=None,
      use_gradient_tape=False,
      unconnected_gradients=None,
      name=None,
  ):
      """Computes the gradients of `func_or_y` wrt to `*xs`.
  
      Args:
       func_or_y: Either a `Tensor` connected to the input `x` or a Python callable
          accepting one `Tensor` of shape of `x` and returning a `Tensor` of any
          shape. The function whose gradient is to be computed. If eagerly
          executing, can only be a callable, i.e., one should not supply a Tensor
          in eager mode.
        xs: Python list of parameters of `f` for which to differentiate. (Can also
          be single `Tensor`.)
        output_gradients: A `Tensor` or list of `Tensor`s the same size as the
          result `ys = f(*xs)` and holding the gradients computed for each `y` in
          `ys`. This argument is forwarded to the underlying gradient implementation
          (i.e., either the `grad_ys` argument of `tf.gradients` or the
          `output_gradients` argument of `tf.GradientTape.gradient`).
          Default value: `None` which maps to a ones-like `Tensor` of `ys`.
        use_gradient_tape: Python `bool` indicating that `tf.GradientTape` should be
          used regardless of `tf.executing_eagerly()` status.
          Default value: `False`.
        unconnected_gradients: An enum `tf.UnconnectedGradients` which specifies the
          gradient value returned when the given input tensors are unconnected.
          Default value: `None`, which maps to `tf.UnconnectedGradients.NONE`.
        name: Python `str` name prefixed to ops created by this function.
          Default value: `None` (i.e., 'gradients').
  
      Returns:
        A `Tensor` with the gradient of `y` wrt each of `xs` or a list of `Tensor`s
        if `xs` is a list.
      """
      unconnected_gradients = (
          unconnected_gradients or tf.UnconnectedGradients.NONE
      )
      f = _prepare_func(func_or_y)
      with tf.name_scope(name or "gradients"):
          xs, is_xs_list_like = _prepare_args(xs)
          if not tf.executing_eagerly() and not use_gradient_tape:
              y = f(*xs)
              grad = tf.gradients(
                  y,
                  xs,
                  grad_ys=output_gradients,
                  unconnected_gradients=unconnected_gradients,
              )
          else:
              if not callable(func_or_y):
                  raise ValueError(
                      "`func_or_y` should be a callable in eager mode or "
                      "when `tf.GradientTape` is used."
                  )
              with tf.GradientTape() as tape:
                  for x in xs:
                      tape.watch(x)
                  y = f(*xs)
              grad = tape.gradient(
                  y,
                  xs,
                  output_gradients=output_gradients,
                  unconnected_gradients=unconnected_gradients,
              )
          if is_xs_list_like:
              return grad
          else:
              return grad[0]
  
file_path: tf-quant-finance/tf_quant_finance/math/gradient.py
imports: import functools
  import tensorflow.compat.v2
label_desc: Use image node_id 2 for calling a global function with example usage: gradients(func_or_y, xs, output_gradients, use_gradient_tape, unconnected_gradients, name) and returns: grad, grad