code: def get_cached_fn(
      fn: Optional[F] = None,
      *,
      max_size: Optional[int] = 16,
  ) -> F:
      """Returns a version of `fn` with cache and that logs statistics."""
  
      def decorator_fn(fn_: F) -> F:
          cached_fn = functools.lru_cache(maxsize=max_size)(fn_)
  
          @functools.wraps(fn_)
          def wrapper(*args, **kwargs):
              try:
                  output = cached_fn(*args, **kwargs)
                  logging.info(
                      "%s cache stats: %s", fn_, cached_fn.cache_info()
                  )
                  return output
              except TypeError as e:
                  # TODO(sacastro): what if this "unhashable type" error occurs because of
                  #   something inside the call to `fn`? Calling the `fn` twice may have
                  #   secondary effects. It's unlikely though.
                  if (
                      (e_args := getattr(e, "args", []))
                      and e_args
                      and isinstance(e_args[0], str)
                      and e_args[0].startswith("unhashable type: ")
                  ):
                      logging.warning(
                          "Cannot cache %s, %s", fn_, e_args[0]
                      )
                      return fn_(*args, **kwargs)
                  else:
                      raise
  
          return wrapper
  
      return decorator_fn if fn is None else decorator_fn(fn)
  
imports: import collections
  from collections.abc import Callable
  from collections.abc import Iterable
  from collections.abc import Mapping
  import functools
  from typing import Any
  from typing import Hashable
  from typing import Literal
  from typing import Optional
  from typing import Sequence
  from typing import TypeVar
  from typing import Union
  from absl import logging
  from clu import metric_writers
  import flax
  from flax import jax_utils
  from flax import traverse_util
  from flax.core.frozen_dict import FrozenDict
  import jax
  import jax.numpy
  import ml_collections
  import numpy
  from scenic.dataset_lib import dataset_utils
  from scenic.projects.lang4video import util
  from scenic.projects.lang4video.model.base_encoders import ImageTextEncoder
  from scenic.train_lib import train_utils
label_desc: Use image node_id 9 for calling a global function with example usage: get_cached_fn(fn) and returns: unknown, wrapper, output, fn_