class_docstr: A class that wraps the execution of a `VM` making it easier for use as a "function".
  
  `Function` is the callable object that does computation.  It has the storage
  of inputs and outputs, performs the packing and unpacking of inputs and
  return values. It implements the square-bracket indexing so that you can
  look up the value of a symbolic node.
  
  Functions are copyable via `Function.copy` and the `copy.copy` interface.
  When a function is copied, this instance is duplicated. Contrast with
  self.maker (instance of `FunctionMaker`) that is shared between copies.
  The meaning of copying a function is that the containers and their current
  values will all be duplicated. This requires that mutable inputs be
  copied, whereas immutable inputs may be shared between copies.
  
  A Function instance is hashable, on the basis of its memory address (its
  id).
  A Function instance is only equal to itself.
  A Function instance may be serialized using the `pickle` or
  `cPickle` modules.  This will save all default inputs, the graph,
  and WRITEME to the pickle file.
  
  A `Function` instance has a `Function.trust_input` field that defaults to
  ``False``. When ``True``, the `Function` will skip all checks on the
  inputs.
  
  Attributes
  ----------
  finder
      Dictionary mapping several kinds of things to containers.
  
      We set an entry in finder for:
      - the index of the input
      - the variable instance the input is based on
      - the name of the input
  
      All entries map to the container or to DUPLICATE if an ambiguity
      is detected.
  inv_finder
      Reverse lookup of `finder`.  It maps containers to `SymbolicInput`\s.
docstr: When allow_gc = False, clear the Variables in storage_map
docstr_tok: ["When","allow_gc","=","False",",","clear","the","Variables","in","storage_map"]
code: def free(self):
      """
      When allow_gc = False, clear the Variables in storage_map
      """
      # 1.no allow_gc return False
      # 2.has allow_gc, if allow_gc is False, return True
      if not getattr(self.vm, "allow_gc", True):
          for key in self.vm.storage_map:
              if not isinstance(key, Constant):
                  self.vm.storage_map[key][0] = None
  
          for node in self.nodes_with_inner_function:
              if hasattr(node.fn, "free"):
                  node.fn.free()
  
imports: import copy
  import copyreg
  import logging
  import time
  import warnings
  from itertools import chain
  from typing import TYPE_CHECKING, Optional
  import numpy
  import pytensor
  import pytensor.compile.profiling
  from pytensor.compile.io import In, SymbolicInput, SymbolicOutput
  from pytensor.compile.ops import deep_copy_op, view_op
  from pytensor.configdefaults import config
  from pytensor.graph.basic import Constant, Variable, ancestors, clone_get_equiv, graph_inputs
  from pytensor.graph.destroyhandler import DestroyHandler
  from pytensor.graph.features import AlreadyThere, Feature, PreserveVariableAttributes
  from pytensor.graph.fg import FunctionGraph
  from pytensor.graph.op import HasInnerGraph
  from pytensor.graph.utils import InconsistencyError, get_variable_trace_string
  from pytensor.link.basic import Container
  from pytensor.link.utils import raise_with_op
label_desc: Use image node_id 8 for calling the Function obj's underlying member method code with example usage: obj.free() without return types