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 an `Apply` node that represent the application of this operation to the given inputs.
  
  This must be implemented by sub-classes.
  
  Returns
  -------
  node: Apply
      The constructed `Apply` node.
docstr_tok: ["Construct","an","`","Apply","`","node","that","represent","the","application","of","this","operation","to","the","given","inputs",".","This","must","be","implemented","by","sub-classes",".","Returns","--","--","--","-","node",":","Apply","The","constructed","`","Apply","`","node","."]
code: def make_node(self, *inputs: Variable) -> Apply:
      """Construct an `Apply` node that represent the application of this operation to the given inputs.
  
      This must be implemented by sub-classes.
  
      Returns
      -------
      node: Apply
          The constructed `Apply` node.
  
      """
      if self.itypes is None:
          raise NotImplementedError(
              "You can either define itypes and otypes, or implement make_node"
          )
  
      if self.otypes is None:
          raise NotImplementedError(
              "You can either define itypes and otypes, or implement make_node"
          )
  
      if len(inputs) != len(self.itypes):
          raise ValueError(
              f"We expected {len(self.itypes)} inputs but got {len(inputs)}."
          )
      if not all(
          expected_type.is_super(var.type)
          for var, expected_type in zip(inputs, self.itypes)
      ):
          raise TypeError(
              f"Invalid input types for Op {self}:\n"
              + "\n".join(
                  f"Input {i}/{len(inputs)}: Expected {inp}, got {out}"
                  for i, (inp, out) in enumerate(
                      zip(self.itypes, (inp.type for inp in inputs)),
                      start=1,
                  )
                  if inp != out
              )
          )
      return Apply(self, inputs, [o() for o in self.otypes])
  
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 1 for calling the Op obj's underlying member method code with example usage: obj.make_node() and returns: Apply