Initial support for symbolic tracing with torch.fx allowing dynamic axes
# What does this PR do?

This PR enables to symbolic trace models without having to specify a fixed batch size and / or sequence length. 
To specify that an axis should not have a fixed shape, the value should be set to -1:

```python
traced = symbolic_trace(
    model,
    input_names=["input_ids", "attention_mask", "token_type_ids"],
    batch_size=-1, # means that batch size should be dynamic
    sequence_length=-1 # means that the sequence length should be dynamic
)
```

Currently, only the following models support dynamic axes:

- Albert
- Bert
- DistilBert
- MobileBert
- MegatronBert
- Electra

Traced models with dynamic axes cannot be retraced out of the box, to solve this 2 functions are provided:

- `prepare_for_retracing`: takes a traced model as input and outputs a model that can be retraced and some information that is needed to get back to dynamic axes
- `restore_after_retracing`: takes a retraced model and the information returned by `prepare_for_retracing` and set the dynamic axes back

Example:
```python
prepared, attributes = prepare_for_retracing(traced)
retraced = some_retracing_func(prepared)
final_model = restore_after_retracing(retraced, attributes)
``` 

To make things less tedious, `retrace_graph_with` is provided: it takes a traced model, and either a Tracer or a tracing function and performs the retracing:

```python
final_model = retrace_graph_with(traced, func=some_tracing_func)
```

Being able to retrace a model is important because that is how quantization can be done for instance.

Finally, this PR also provides sanity checks that validate that symbolic tracing is available for the model provided to `symbolic_trace`, and that it can be traced with dynamic axes if the user asks for it.
@sgugger What do you think of the way I've changed things regarding the config classes imports?