ASN.1 BER Encoding and Decoding
Some ideas:

String concatenation

The method you're using for string concatenation (successively using the += operator) is the slowest method in Python for constructing strings.  Consider instead creating a list of strings and concatenating them at the end using return ''.join(created_strings).  Because your BER encoder is likely to be used with a protocol, speed may be important.

Checking of inputs

Your cls, pc and tag elements are not checked on input to the ber_encode routine and would allow constructs such as ber_encode(0xc3,7,3,"bongo") which gets coded with a tag of 0xcd.  That isn't necessarily wrong but it's not what I might have expected.

Orthogonality of ber_encode and ber_decode

It's not unreasonable for a user of your functions to assume that the two complementary functions can each be fed the output of the other, but that's not the case for these functions.  While ber_decode will happily digest the output of ber_encode, what ber_decode produces is a named tuple rather than an output that's compatible with ber_encode's input requirements.  Again, this isn't necessarily wrong, but it is a potential impediment to users of your functions.

Error checking

Generally, the code does a pretty good job of validating inputs and throwing appropriate errors, but there is at least one case which is accepted that should probably throw an error.  Specifically, 

ber_decode(b'\x86\xff'+('a'*256).encode(encoding='ascii'))


results in a BER value which is 129 bytes long.  It's probably worth double checking ITU X.690 section 8.1.3.5 which says that an encoded length value of 11111111b shall not be used.

Similarly, 

ber_decode(b'\x86\x80'+('a'*256).encode(encoding='ascii'))


is decoded as three BER encodings, the first of which is 128 bytes long (which is suspect), the second is 97 bytes long (which is OK) and the third is 27 bytes long, which may or may not be OK, but shouldn't a truncated message throw an exception?

Test vectors

You may simply have omitted them from the posted code, but I'd highly recommend including test vectors with the code. Python has a number of ways to do testing including doctest and unittest. Not only do they help you make sure you've considered many different types of input (both good and bad), but they also serve as documentation for users of the functions.