code: def make_tf_callable(
      session_or_none: Optional["tf1.Session"],
      dynamic_shape: bool = False,
  ) -> Callable:
      """Returns a function that can be executed in either graph or eager mode.
  
      The function must take only positional args.
  
      If eager is enabled, this will act as just a function. Otherwise, it
      will build a function that executes a session run with placeholders
      internally.
  
      Args:
          session_or_none: tf.Session if in graph mode, else None.
          dynamic_shape: True if the placeholders should have a dynamic
              batch dimension. Otherwise they will be fixed shape.
  
      Returns:
          A function that can be called in either eager or static-graph mode.
      """
  
      if tf.executing_eagerly():
          assert session_or_none is None
      else:
          assert session_or_none is not None
  
      def make_wrapper(fn):
          # Static-graph mode: Create placeholders and make a session call each
          # time the wrapped function is called. Returns the output of this
          # session call.
          if session_or_none is not None:
              args_placeholders = []
              kwargs_placeholders = {}
  
              symbolic_out = [None]
  
              def call(*args, **kwargs):
                  args_flat = []
                  for a in args:
                      if type(a) is list:
                          args_flat.extend(a)
                      else:
                          args_flat.append(a)
                  args = args_flat
  
                  # We have not built any placeholders yet: Do this once here,
                  # then reuse the same placeholders each time we call this
                  # function again.
                  if symbolic_out[0] is None:
                      with session_or_none.graph.as_default():
  
                          def _create_placeholders(path, value):
                              if dynamic_shape:
                                  if len(value.shape) > 0:
                                      shape = (None,) + value.shape[1:]
                                  else:
                                      shape = ()
                              else:
                                  shape = value.shape
                              return tf1.placeholder(
                                  dtype=value.dtype,
                                  shape=shape,
                                  name=".".join([str(p) for p in path]),
                              )
  
                          placeholders = tree.map_structure_with_path(
                              _create_placeholders, args
                          )
                          for ph in tree.flatten(placeholders):
                              args_placeholders.append(ph)
  
                          placeholders = tree.map_structure_with_path(
                              _create_placeholders, kwargs
                          )
                          for k, ph in placeholders.items():
                              kwargs_placeholders[k] = ph
  
                          symbolic_out[0] = fn(
                              *args_placeholders, **kwargs_placeholders
                          )
                  feed_dict = dict(
                      zip(args_placeholders, tree.flatten(args))
                  )
                  tree.map_structure(
                      lambda ph, v: feed_dict.__setitem__(ph, v),
                      kwargs_placeholders,
                      kwargs,
                  )
                  ret = session_or_none.run(symbolic_out[0], feed_dict)
                  return ret
  
              return call
          # Eager mode (call function as is).
          else:
              return fn
  
      return make_wrapper
  
imports: import logging
  from typing import Any, Callable, List, Optional, Type, TYPE_CHECKING, Union
  import gymnasium
  import numpy
  import tree
  from gymnasium.spaces import Discrete, MultiDiscrete
  from ray.rllib.utils.annotations import PublicAPI, DeveloperAPI
  from ray.rllib.utils.framework import try_import_tf
  from ray.rllib.utils.spaces.space_utils import get_base_struct_from_space
  from ray.rllib.utils.typing import LocalOptimizer, ModelGradients, PartialAlgorithmConfigDict, SpaceStruct, TensorStructType, TensorType
label_desc: Use image node_id 9 for calling a global function with example usage: make_tf_callable(session_or_none, dynamic_shape) and returns: make_wrapper, call, fn, ret, tf1