### Apache Airflow version

2.6.1

### What happened

When doing `.partial()` and `.expand()` on any operator which has an instance property (e.g. `@property`) of `operator_extra_links` the `MappedOperator` does not handle it properly, causing the dag to fail to import.

The `BatchOperator` from `airflow.providers.amazon.aws.operators.batch` is one example of an operator which defines `operator_extra_links` on a per-instance basis.

### What you think should happen instead

The dag should not fail to import (especially when using the AWS `BatchOperator`!) Either:

- If per-instance `operator_extra_links` is deemed disallowed behaviour
  - `MappedOperator` should detect it's a property and give a more helpful error message
  - `BatchOperator` from the AWS provider should be changed. If I need to open another ticket elsewhere for that please let me know
- If per-instance `operator_extra_links` is allowed
  - `MappedOperator` needs to be adjusted to account for that

### How to reproduce

```
import pendulum
from airflow.models.baseoperator import BaseOperator
from airflow.decorators import dag, task
class BadOperator(BaseOperator):
    def __init__(self, *args, some_argument: str, **kwargs):
        super().__init__(*args, some_argument, **kwargs)

    @property
    def operator_extra_links(self):
        # !PROBLEMATIC FUNCTION!
        # ... Some code to create a collection of `BaseOperatorLink`s dynamically
        return tuple()

@dag(
    schedule=None,
    start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
    catchup=False,
    tags=["example"]
)
def airflow_is_bad():
    """
    Example to demonstrate issue with airflow API
    """

    @task
    def create_arguments():
        return [1,2,3,4]

    bad_operator_test_group = BadOperator.partial(
        task_id="bad_operator_test_group",
    ).expand(some_argument=create_arguments())

dag = airflow_is_bad()
```
Put this in your dags folder, Airflow will fail to import the dag with error
```
Broken DAG: [<USER>/airflow/dags/airflow_is_bad_minimal_example.py] Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/airflow/serialization/serialized_objects.py", line 825, in _serialize_node
    serialize_op["_operator_extra_links"] = cls._serialize_operator_extra_links(
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/airflow/serialization/serialized_objects.py", line 1165, in _serialize_operator_extra_links
    for operator_extra_link in operator_extra_links:
TypeError: 'property' object is not iterable
```
Commenting out the `operator_extra_links` from the `BadOperator` in the example will allow the dag to be imported fine

### Operating System

macOS Ventura 13.4

### Versions of Apache Airflow Providers

```
apache-airflow-providers-amazon==8.0.0
apache-airflow-providers-common-sql==1.4.0
apache-airflow-providers-ftp==3.3.1
apache-airflow-providers-google==10.0.0
apache-airflow-providers-http==4.3.0
apache-airflow-providers-imap==3.1.1
apache-airflow-providers-postgres==5.4.0
apache-airflow-providers-sqlite==3.3.2
```

### Deployment

Official Apache Airflow Helm Chart

### Deployment details

_No response_

### Anything else

I found adjusting `operator_extra_links` on `BatchOperator` to be `operator_extra_links = (BatchJobDetailsLink(), BatchJobDefinitionLink(), BatchJobQueueLink(), CloudWatchEventsLink())` solved my issue and made it run fine, however I've no idea if that's safe or generalises because I'm not sure what `operator_extra_links` is actually for internally.

### Are you willing to submit PR?

- [ ] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)

elif k == "subdag":
                v = SerializedDAG.deserialize_dag(v)
            elif k in {"retry_delay", "execution_timeout", "sla", "max_retry_delay"}:
                v = cls._deserialize_timedelta(v)
            elif k in encoded_op["template_fields"]:
                pass
            elif k == "resources":
                v = Resources.from_dict(v)
            elif k.endswith("_date"):
                v = cls._deserialize_datetime(v)
            elif k == "_operator_extra_links":
                if cls._load_operator_extra_links:
                    op_predefined_extra_links = cls._deserialize_operator_extra_links(v)
                    
                    op_predefined_extra_links.update(op_extra_links_from_plugin)
                else:
                    op_predefined_extra_links = {}
                v = list(op_predefined_extra_links.values())
                k = "operator_extra_links"
            elif k == "deps":
                v = cls._deserialize_deps(v)
            elif k == "params":
                v = cls._deserialize_params_dict(v)
                if op.params:  
                    v, new = op.params, v
                    v.update(new)
            elif k == "partial_kwargs":
                v = {arg: cls.deserialize(value) for arg, value in v.items()}
            elif k in {"expand_input", "op_kwargs_expand_input"}:
                v = _ExpandInputRef(v["type"], cls.deserialize(v["value"]))