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: Calculate the function on the inputs and put the variables in the output storage.
  
  Parameters
  ----------
  node
      The symbolic `Apply` node that represents this computation.
  inputs
      Immutable sequence of non-symbolic/numeric inputs.  These
      are the values of each `Variable` in :attr:`node.inputs`.
  output_storage
      List of mutable single-element lists (do not change the length of
      these lists).  Each sub-list corresponds to value of each
      `Variable` in :attr:`node.outputs`.  The primary purpose of this method
      is to set the values of these sub-lists.
  
  Notes
  -----
  The `output_storage` list might contain data. If an element of
  output_storage is not ``None``, it has to be of the right type, for
  instance, for a `TensorVariable`, it has to be a NumPy ``ndarray``
  with the right number of dimensions and the correct dtype.
  Its shape and stride pattern can be arbitrary. It is not
  guaranteed that such pre-set values were produced by a previous call to
  this :meth:`Op.perform`; they could've been allocated by another
  `Op`'s `perform` method.
  An `Op` is free to reuse `output_storage` as it sees fit, or to
  discard it and allocate new memory.
docstr_tok: ["Calculate","the","function","on","the","inputs","and","put","the","variables","in","the","output","storage",".","Parameters","--","--","--","--","--","node","The","symbolic","`","Apply","`","node","that","represents","this","computation",".","inputs","Immutable","sequence","of","non-symbolic\/numeric","inputs",".","These","are","the","values","of","each","`","Variable","`","in",":","attr",":","`","node.inputs","`",".","output_storage","List","of","mutable","single-element","lists","(","do","not","change","the","length","of","these","lists",")",".","Each","sub-list","corresponds","to","value","of","each","`","Variable","`","in",":","attr",":","`","node.outputs","`",".","The","primary","purpose","of","this","method","is","to","set","the","values","of","these","sub-lists",".","Notes","--","--","-","The","`","output_storage","`","list","might","contain","data",".","If","an","element","of","output_storage","is","not","``","None","``",",","it","has","to","be","of","the","right","type",",","for","instance",",","for","a","`","TensorVariable","`",",","it","has","to","be","a","NumPy","``","ndarray","``","with","the","right","number","of","dimensions","and","the","correct","dtype",".","Its","shape","and","stride","pattern","can","be","arbitrary",".","It","is","not","guaranteed","that","such","pre-set","values","were","produced","by","a","previous","call","to","this",":","meth",":","`","Op.perform","`",";","they","could","'ve","been","allocated","by","another","`","Op","`","'s","`","perform","`","method",".","An","`","Op","`","is","free","to","reuse","`","output_storage","`","as","it","sees","fit",",","or","to","discard","it","and","allocate","new","memory","."]
code: def perform(
      self,
      node: Apply,
      inputs: Sequence[Any],
      output_storage: OutputStorageType,
  ) -> None:
      """Calculate the function on the inputs and put the variables in the output storage.
  
      Parameters
      ----------
      node
          The symbolic `Apply` node that represents this computation.
      inputs
          Immutable sequence of non-symbolic/numeric inputs.  These
          are the values of each `Variable` in :attr:`node.inputs`.
      output_storage
          List of mutable single-element lists (do not change the length of
          these lists).  Each sub-list corresponds to value of each
          `Variable` in :attr:`node.outputs`.  The primary purpose of this method
          is to set the values of these sub-lists.
  
      Notes
      -----
      The `output_storage` list might contain data. If an element of
      output_storage is not ``None``, it has to be of the right type, for
      instance, for a `TensorVariable`, it has to be a NumPy ``ndarray``
      with the right number of dimensions and the correct dtype.
      Its shape and stride pattern can be arbitrary. It is not
      guaranteed that such pre-set values were produced by a previous call to
      this :meth:`Op.perform`; they could've been allocated by another
      `Op`'s `perform` method.
      An `Op` is free to reuse `output_storage` as it sees fit, or to
      discard it and allocate new memory.
  
      """
  
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 7 for calling the Op obj's underlying member method code with example usage: obj.perform(node, inputs, output_storage) without return types