tf.keras.Model with nested dictionary inputs fails to serialize/deserialize
@burnpanck,
Thank you for reporting the issue. We are currently investigating the issue, and I kindly request some time to thoroughly analyze the problem in order to offer a resolution. Thank you! @sachinprasadhs,
I was able to reproduce the issue on tensorflow v2.14, v2.13 and [tf-nightly](https://colab.research.google.com/gist/tilakrayal/ce17db0b619e5197b6c526dcfa819c10/untitled1464.ipynb). Kindly find the gist of it [here](https://colab.research.google.com/gist/tilakrayal/2ad827cca47992b6e5c756b92d395c43/untitled1465.ipynb). Hi,

Going forward `Keras` with the new multi backend support in `Keras 3` it will no longer support deeply nested inputs/outputs more than 1 level in `Model()`.

You would have to provide the inputs/outputs in the same level as shown below.

```python
import tensorflow as tf

@tf.keras.saving.register_keras_serializable(package="MyPackage")
class DummyModel(tf.keras.Model):
    def __init__(self, name=None):
        super().__init__(name=name)
        self.sublayer = tf.keras.layers.Dense(16)
    def call(self, x, **kw):
        a = x["a"]
        b = x["b"]
        c = x["c"]
        return self.sublayer(tf.concat([a,b,c], axis=-1))

model = DummyModel()
out = model(dict(
    a = tf.keras.Input(3,dtype=tf.float32),
    b = tf.keras.Input(4,dtype=tf.float32),
    c = tf.keras.Input(5,dtype=tf.float32),
    )
)
model.summary()

model.save("temp.keras")

tf.keras.saving.load_model("temp.keras")
``` What a pity. Given that one can always create a wrapper around model calls that serialises and deserialises nested dicts into a flat dict or even a list, obviously there is no fundamental reason why this could not be supported. In fact, if I remember correctly, that's what I did during TF 1 days. It's just that now, we have to again decide between writing lots of unnecessary boiler-plate or having non-expressive APIs.
Where do I post a feature request for TF 3? For `Keras 3` you can post the issue in https://github.com/keras-team/keras/issues and close the issue here. 
 This issue is stale because it has been open for 7 days with no activity. It will be closed if no further activity occurs. Thank you. This issue was closed because it has been inactive for 7 days since being marked as stale. Please reopen if you'd like to work on this further. Are you satisfied with the resolution of your issue?
<a href="https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=Yes&entry.2137816233=https://github.com/tensorflow/tensorflow/issues/62192">Yes</a>
<a href="https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=No&entry.2137816233=https://github.com/tensorflow/tensorflow/issues/62192">No</a>
 Ok, if TF really doesn't want to support nested dictionaries in some or all of their APIs, then that should be documented, and ideally it should produce actionable error messages. Right now, the TF documentation explicitly states that the `.keras` format is the chosen method, but it doesn't support all features previous formats did. So this is a breaking change, and should be documented very explicitly. I thus don't think that this issue can be closed, whether or not the feature is going to be supported. It is either an implementation bug or a documentation bug. It is documented here and it will be available in keras.io soon.

https://github.com/keras-team/keras-io/blob/be3791ecde06d8bae22c885868983ddaf1af2cd7/guides/migrate_to_keras_3.py#L203-L245 Ok, that makes sense - thanks for pointer.
Info:
- Issue type: **Bug**
- Have you reproduced the bug with TensorFlow Nightly? No
- Source: binary
- TensorFlow version: 2.14.0
- Custom code: No
- OS platform and distribution: macOS 13.6
- Python version: 3.11
- CUDA/cuDNN version: none

### Current behavior?

When trying to serialize/deserialize a `tf.keras.Model` nested input shapes cause an error.

Note that this has been observed many years back in #37061, which was closed because their MVP included a `tf.keras.Sequential` which was deemed as not supported. However, the issue has nothing to do with `tf.keras.Sequential` at all, and instead lies purely in the deserialisation code of keras.

### Standalone code to reproduce the issue

```shell
import tensorflow as tf

@tf.keras.saving.register_keras_serializable(package="MyPackage")
class DummyModel(tf.keras.Model):
    def __init__(self, name=None):
        super().__init__(name=name)
        self.sublayer = tf.keras.layers.Dense(16)
    def call(self, x, **kw):
        a = x["a"]
        nested = x["nested"]
        b = nested["b"]
        c = nested["c"]
        return self.sublayer(tf.concat([a,b,c], axis=-1))

model = DummyModel()
out = model(dict(
    a = tf.keras.Input(3,dtype=tf.float32),
    nested = dict(
        b = tf.keras.Input(4,dtype=tf.float32),
        c = tf.keras.Input(5,dtype=tf.float32),
    ),
))
model.summary()

model.save("temp.keras")

tf.keras.saving.load_model("temp.keras")
```


### Relevant log output

```shell
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/tensorflow/python/framework/tensor_shape.py:851, in TensorShape.__init__(self, dims)
    850 try:
--> 851   self._dims.append(as_dimension(d).value)
    852 except TypeError as e:

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/tensorflow/python/framework/tensor_shape.py:741, in as_dimension(value)
    740 else:
--> 741   return Dimension(value)

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/tensorflow/python/framework/tensor_shape.py:217, in Dimension.__init__(self, value)
    216 except AttributeError:
--> 217   raise TypeError(
    218       "Dimension value must be integer or None or have "
    219       "an __index__ method, got value '{0!r}' with type '{1!r}'".format(
    220           value, type(value))) from None
    221 if self._value < 0:

TypeError: Dimension value must be integer or None or have an __index__ method, got value ''b'' with type '<class 'str'>'

The above exception was the direct cause of the following exception:

TypeError                                 Traceback (most recent call last)
File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/tensorflow/python/eager/execute.py:204, in make_shape(v, arg_name)
    203 try:
--> 204   shape = tensor_shape.as_shape(v)
    205 except TypeError as e:

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/tensorflow/python/framework/tensor_shape.py:1526, in as_shape(shape)
   1525 else:
-> 1526   return TensorShape(shape)

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/tensorflow/python/framework/tensor_shape.py:853, in TensorShape.__init__(self, dims)
    852   except TypeError as e:
--> 853     raise TypeError(
    854         "Failed to convert '{0!r}' to a shape: '{1!r}'"
    855         "could not be converted to a dimension. A shape should "
    856         "either be single dimension (e.g. 10), or an iterable of "
    857         "dimensions (e.g. [1, 10, None]).".format(dims, d)) from e
    858 self._dims = tuple(self._dims)

TypeError: Failed to convert '{'b': [None, 4], 'c': [None, 5]}' to a shape: ''b''could not be converted to a dimension. A shape should either be single dimension (e.g. 10), or an iterable of dimensions (e.g. [1, 10, None]).

During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
Cell In[6], line 1
----> 1 tf.keras.saving.load_model("temp.keras")

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/saving/saving_api.py:254, in load_model(filepath, custom_objects, compile, safe_mode, **kwargs)
    249     if kwargs:
    250         raise ValueError(
    251             "The following argument(s) are not supported "
    252             f"with the native Keras format: {list(kwargs.keys())}"
    253         )
--> 254     return saving_lib.load_model(
    255         filepath,
    256         custom_objects=custom_objects,
    257         compile=compile,
    258         safe_mode=safe_mode,
    259     )
    261 # Legacy case.
    262 return legacy_sm_saving_lib.load_model(
    263     filepath, custom_objects=custom_objects, compile=compile, **kwargs
    264 )

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/saving/saving_lib.py:281, in load_model(filepath, custom_objects, compile, safe_mode)
    278             asset_store.close()
    280 except Exception as e:
--> 281     raise e
    282 else:
    283     return model

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/saving/saving_lib.py:246, in load_model(filepath, custom_objects, compile, safe_mode)
    244 # Construct the model from the configuration file in the archive.
    245 with ObjectSharingScope():
--> 246     model = deserialize_keras_object(
    247         config_dict, custom_objects, safe_mode=safe_mode
    248     )
    250 all_filenames = zf.namelist()
    251 if _VARS_FNAME + ".h5" in all_filenames:

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/saving/serialization_lib.py:731, in deserialize_keras_object(config, custom_objects, safe_mode, **kwargs)
    729 build_config = config.get("build_config", None)
    730 if build_config:
--> 731     instance.build_from_config(build_config)
    732 compile_config = config.get("compile_config", None)
    733 if compile_config:

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/engine/base_layer.py:2331, in Layer.build_from_config(self, config)
   2329 input_shape = config["input_shape"]
   2330 if input_shape is not None:
-> 2331     self.build(input_shape)

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/engine/training.py:494, in Model.build(self, input_shape)
    489     x = [
    490         base_layer_utils.generate_placeholders_from_shape(shape)
    491         for shape in input_shape
    492     ]
    493 elif isinstance(input_shape, dict):
--> 494     x = {
    495         k: base_layer_utils.generate_placeholders_from_shape(
    496             shape
    497         )
    498         for k, shape in input_shape.items()
    499     }
    500 else:
    501     x = base_layer_utils.generate_placeholders_from_shape(
    502         input_shape
    503     )

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/engine/training.py:495, in <dictcomp>(.0)
    489     x = [
    490         base_layer_utils.generate_placeholders_from_shape(shape)
    491         for shape in input_shape
    492     ]
    493 elif isinstance(input_shape, dict):
    494     x = {
--> 495         k: base_layer_utils.generate_placeholders_from_shape(
    496             shape
    497         )
    498         for k, shape in input_shape.items()
    499     }
    500 else:
    501     x = base_layer_utils.generate_placeholders_from_shape(
    502         input_shape
    503     )

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/engine/base_layer_utils.py:189, in generate_placeholders_from_shape(shape)
    188 def generate_placeholders_from_shape(shape):
--> 189     return tf1.placeholder(shape=shape, dtype=backend.floatx())

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/tensorflow/python/ops/array_ops.py:3283, in placeholder(dtype, shape, name)
   3279 if context.executing_eagerly():
   3280   raise RuntimeError("tf.placeholder() is not compatible with "
   3281                      "eager execution.")
-> 3283 return gen_array_ops.placeholder(dtype=dtype, shape=shape, name=name)

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/tensorflow/python/ops/gen_array_ops.py:7071, in placeholder(dtype, shape, name)
   7069 if shape is None:
   7070   shape = None
-> 7071 shape = _execute.make_shape(shape, "shape")
   7072 _, _, _op, _outputs = _op_def_library._apply_op_helper(
   7073       "Placeholder", dtype=dtype, shape=shape, name=name)
   7074 _result = _outputs[:]

File ~/.pyenv/versions/3.11.3/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/tensorflow/python/eager/execute.py:206, in make_shape(v, arg_name)
    204   shape = tensor_shape.as_shape(v)
    205 except TypeError as e:
--> 206   raise TypeError("Error converting %s to a TensorShape: %s." % (arg_name, e))
    207 except ValueError as e:
    208   raise ValueError("Error converting %s to a TensorShape: %s." %
    209                    (arg_name, e))

TypeError: Error converting shape to a TensorShape: Failed to convert '{'b': [None, 4], 'c': [None, 5]}' to a shape: ''b''could not be converted to a dimension. A shape should either be single dimension (e.g. 10), or an iterable of dimensions (e.g. [1, 10, None])..
```
