class_docstr: A class that models and constructs operations in a graph.
  
  A `Op` instance has several responsibilities:
  
  * construct `Apply` nodes via :meth:`Op.make_node` method,
  * perform the numeric calculation of the modeled operation via the
    :meth:`Op.perform` method,
  * and (optionally) build the gradient-calculating sub-graphs via the
    :meth:`Op.grad` method.
  
  To see how `Op`, `Type`, `Variable`, and `Apply` fit together see the
  page on :doc:`graph`.
  
  For more details regarding how these methods should behave: see the `Op
  Contract` in the sphinx docs (advanced tutorial on `Op` making).
class_docstr_tok: ["A","class","that","models","and","constructs","operations","in","a","graph",".","A","`","Op","`","instance","has","several","responsibilities",":","*","construct","`","Apply","`","nodes","via",":","meth",":","`","Op.make_node","`","method",",","*","perform","the","numeric","calculation","of","the","modeled","operation","via","the",":","meth",":","`","Op.perform","`","method",",","*","and","(","optionally",")","build","the","gradient-calculating","sub-graphs","via","the",":","meth",":","`","Op.grad","`","method",".","To","see","how","`","Op","`",",","`","Type","`",",","`","Variable","`",",","and","`","Apply","`","fit","together","see","the","page","on",":","doc",":","`","graph","`",".","For","more","details","regarding","how","these","methods","should","behave",":","see","the","`","Op","Contract","`","in","the","sphinx","docs","(","advanced","tutorial","on","`","Op","`","making",")","."]
docstr: Construct a graph for the gradient with respect to each input variable.
  
  Each returned `Variable` represents the gradient with respect to that
  input computed based on the symbolic gradients with respect to each
  output. If the output is not differentiable with respect to an input,
  then this method should return an instance of type `NullType` for that
  input.
  
  Using the reverse-mode AD characterization given in [1]_, for a
  :math:`C = f(A, B)` representing the function implemented by the `Op`
  and its two arguments :math:`A` and :math:`B`, given by the
  `Variable`\s in `inputs`, the values returned by `Op.grad` represent
  the quantities :math:`\bar{A} \equiv \frac{\partial S_O}{A}` and
  :math:`\bar{B}`, for some scalar output term :math:`S_O` of :math:`C`
  in
  
  .. math::
  
      \operatorname{Tr}\left(\bar{C}^\top dC\right) =
          \operatorname{Tr}\left(\bar{A}^\top dA\right) +
          \operatorname{Tr}\left(\bar{B}^\top dB\right)
  
  
  Parameters
  ----------
  inputs
      The input variables.
  output_grads
      The gradients of the output variables.
  
  Returns
  -------
  grads
      The gradients with respect to each `Variable` in `inputs`.
  
  References
  ----------
  .. [1] Giles, Mike. 2008. “An Extended Collection of Matrix Derivative Results for Forward and Reverse Mode Automatic Differentiation.”
docstr_tok: ["Construct","a","graph","for","the","gradient","with","respect","to","each","input","variable",".","Each","returned","`","Variable","`","represents","the","gradient","with","respect","to","that","input","computed","based","on","the","symbolic","gradients","with","respect","to","each","output",".","If","the","output","is","not","differentiable","with","respect","to","an","input",",","then","this","method","should","return","an","instance","of","type","`","NullType","`","for","that","input",".","Using","the","reverse-mode","AD","characterization","given","in","[","1","]","_",",","for","a",":","math",":","`","C","=","f","(","A",",","B",")","`","representing","the","function","implemented","by","the","`","Op","`","and","its","two","arguments",":","math",":","`","A","`","and",":","math",":","`","B","`",",","given","by","the","`","Variable","`","\\s","in","`","inputs","`",",","the","values","returned","by","`","Op.grad","`","represent","the","quantities",":","math",":","`","\\bar","{","A","}","\\equiv","\\frac","{","\\partial","S_O","}","{","A","}","`","and",":","math",":","`","\\bar","{","B","}","`",",","for","some","scalar","output","term",":","math",":","`","S_O","`","of",":","math",":","`","C","`","in","..","math",":",":","\\operatorname","{","Tr","}","\\left","(","\\bar","{","C","}","^\\top","dC\\right",")","=","\\operatorname","{","Tr","}","\\left","(","\\bar","{","A","}","^\\top","dA\\right",")","+","\\operatorname","{","Tr","}","\\left","(","\\bar","{","B","}","^\\top","dB\\right",")","Parameters","--","--","--","--","--","inputs","The","input","variables",".","output_grads","The","gradients","of","the","output","variables",".","Returns","--","--","--","-","grads","The","gradients","with","respect","to","each","`","Variable","`","in","`","inputs","`",".","References","--","--","--","--","--","..","[","1","]","Giles",",","Mike",".","2008",".","\u201c","An","Extended","Collection","of","Matrix","Derivative","Results","for","Forward","and","Reverse","Mode","Automatic","Differentiation",".","\u201d"]
code: def grad(
      self, inputs: Sequence[Variable], output_grads: Sequence[Variable]
  ) -> list[Variable]:
      r"""Construct a graph for the gradient with respect to each input variable.
  
      Each returned `Variable` represents the gradient with respect to that
      input computed based on the symbolic gradients with respect to each
      output. If the output is not differentiable with respect to an input,
      then this method should return an instance of type `NullType` for that
      input.
  
      Using the reverse-mode AD characterization given in [1]_, for a
      :math:`C = f(A, B)` representing the function implemented by the `Op`
      and its two arguments :math:`A` and :math:`B`, given by the
      `Variable`\s in `inputs`, the values returned by `Op.grad` represent
      the quantities :math:`\bar{A} \equiv \frac{\partial S_O}{A}` and
      :math:`\bar{B}`, for some scalar output term :math:`S_O` of :math:`C`
      in
  
      .. math::
  
          \operatorname{Tr}\left(\bar{C}^\top dC\right) =
              \operatorname{Tr}\left(\bar{A}^\top dA\right) +
              \operatorname{Tr}\left(\bar{B}^\top dB\right)
  
  
      Parameters
      ----------
      inputs
          The input variables.
      output_grads
          The gradients of the output variables.
  
      Returns
      -------
      grads
          The gradients with respect to each `Variable` in `inputs`.
  
      References
      ----------
      .. [1] Giles, Mike. 2008. “An Extended Collection of Matrix Derivative Results for Forward and Reverse Mode Automatic Differentiation.”
  
      """
      raise NotImplementedError()
  
imports: import copy
  import sys
  import warnings
  from abc import ABC, abstractmethod
  from collections.abc import Sequence
  from typing import TYPE_CHECKING, Any, Callable, Optional, Protocol, TypeVar, Union, cast
  import pytensor
  from pytensor.configdefaults import config
  from pytensor.graph.basic import Apply, Variable
  from pytensor.graph.utils import MetaObject, TestValueError, add_tag_trace, get_variable_trace_string
label_desc: Use image node_id 4 for calling the Op obj's underlying member method code with example usage: obj.grad(inputs, output_grads) without return types