To elaborate on [@Hikariztw 's answer][1]

Using the code from https://blender.stackexchange.com/a/141207/15543 as an example.

Update the property group.

    class MaterialSlot(PropertyGroup):
        def get_name(self):
            return self.get("name", "Foo")
    
        def set_name(self, value):
            oldname = self.get("name", "Foo")   
            self["name"] = value
            print(oldname, value)
            
        material : PointerProperty(type=bpy.types.Material)
        name : StringProperty(
                default="Foo", 
                get=get_name, 
                set=set_name)

*Note the example code uses the material name in list UI class. Change to show `item` in draw method to show collection item name instead.*

    layout.prop(item, "name", text= "", emboss=False, icon_value=layout.icon(ma))



Python console code, added a new scene material slot.  It is given the default name "Foo".  Updating the name to "Bar", in this case via console, same if done via UI, and the setter is called.  Which prints old name "Foo" and new name "Bar"

    >>> s = C.scene.material_slots.add()
    >>> s.name
    'Foo'
    
    >>> s.name = "Bar"
    Foo Bar

and again from "Bar" to "Choo"

    >>> s.name = "Choo"
    Bar Choo


But here is the "rub" re the property default value.  The  `PropertyGroup` class  already has a name attribute.  When a new item is first added, it doesn't use the name property default of "Foo", but rather defaults to "".

    >>> C.scene.material_slots.clear()
    >>> s = C.scene.material_slots.add()
    >>> s.name
    'Foo'
    
    >>> C.scene.material_slots.keys()
    ['']

ie collection has a `material_slots[""]` member rather than `material_slots["Foo"]`  However if we set it implicitly, it picks up as expected... which is usual practice I suppose.
    
    >>> s.name = "Foo"
    Foo Foo
    
    >>> C.scene.material_slots.keys()
    ['Foo']


EDIT re comment

> so when I update the list element's name I need to find all objects
> with the original element name and then change it to the new name

For example above, to set all items with old name to new name, do this on a custom property level too. Add something like below to `set_name` method above.

    if oldname != value:
        same = [s for s in self.id_data.material_slots
                if oldname == s.get("name", "Foo")]
        for s in same:
            s["name"] = value


  [1]: https://blender.stackexchange.com/a/141562/15543