code: def backward(outputs, out_grads=None, retain_graph=False):
      
      assert isinstance(outputs, (list, tuple)), \
          "outputs must be a list or tuple of NDArrays"
  
      if out_grads is None:
          check_call(_LIB.MXAutogradBackward(
              len(outputs),
              c_handle_array(outputs),
              ctypes.c_void_p(0),
              ctypes.c_int(retain_graph)))
          return
  
      ograd_handles = []
      for arr in out_grads:
          if arr is not None:
              ograd_handles.append(arr.handle)
          else:
              ograd_handles.append(NDArrayHandle(0))
      assert len(ograd_handles) == len(outputs), \
          "outputs and out_grads must have the same length"
  
      check_call(_LIB.MXAutogradBackward(
          len(outputs),
          c_handle_array(outputs),
          c_array(NDArrayHandle, ograd_handles),
          ctypes.c_int(retain_graph)))
docs: Compute the gradients of outputs w.r.t variables.
  
      Parameters
      ----------
      outputs: list of NDArray
      out_grads: list of NDArray or None