code: def build(f: Callable[..., Any], *args, **kwargs):
      r"""Builds a module by creating all parameters but not computing any output.
  
          >>> mod = snt.nets.MLP([1000, 10])
          >>> snt.build(mod, [None, 28 * 28])
          TensorSpec(shape=(None, 10), dtype=tf.float32, name=None)
          >>> mod.variables
          (<tf.Variable 'mlp/linear_0/b:0' shape=(1000,) ...>,
           <tf.Variable 'mlp/linear_0/w:0' shape=(784, 1000) ...>,
           <tf.Variable 'mlp/linear_1/b:0' shape=(10,) ...>,
           <tf.Variable 'mlp/linear_1/w:0' shape=(1000, 10) ...>)
  
      Args:
        f: A function or callable :class:`Module` that will create variables.
        *args: Positional arguments to supply to ``f``. Note that positional
          arguments that are sequences of None/ints are converted to
          :tf:`TensorSpec` instances.
        **kwargs: Keyword arguments to pass to the module.
  
      Returns:
        The output of ``f`` with any :tf:`Tensor`\ s replaced by :tf:`TensorSpec`.
      """
      f = tf.function(f)
      args = map(_promote_shapes, args)
      # NOTE: We use a concrete function to ensure that weights are created and
      # initialized, but other stateful ops (e.g. updating weights) are not.
      cf = f.get_concrete_function(*args, **kwargs)
      return tree.map_structure(
          _maybe_tensor_spec, cf.output_shapes, cf.output_dtypes
      )
  
imports: from typing import Any, Callable
  import tensorflow
  import tree
label_desc: Use image node_id 4 for calling a global function with example usage: build(f) and returns: tree